package com.cloudbroker.bcs.platform.ltb.common.util;

import com.alibaba.fastjson.JSON;
import com.cloudbroker.bcs.common.model.SessionIdentity;
import com.cloudbroker.bcs.common.util.DateTimeUtil;
import com.cloudbroker.bcs.common.util.IDUtil;
import com.cloudbroker.bcs.common.util.ValueUtil;
import com.cloudbroker.bcs.platform.ltb.common.config.ConfigValues;
import com.cloudbroker.bcs.platform.ltb.common.constant.CacheKeys;
import com.cloudbroker.bcs.platform.ltb.common.constant.type.PlatformType;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class SessionHelper extends com.cloudbroker.bcs.common.util.SessionHelper {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(SessionHelper.class);
    
    private static SessionHelper instance = new SessionHelper();
    
    public static SessionHelper getInstance() {
        return instance;
    }
    
    private SessionHelper() {
        init();
    }
    
    private List<String> sessionPrefixs = new ArrayList<String>();
    
    public void init() {
        sessionPrefixs.add(CacheKeys.ACCESS_TOKEN_PREFIX);
    }
    
    @Override
    protected CacheHelper getCacheHelper() {
        return CacheHelper.getInstance();
    }
    
    @Override
    protected int getSessionTimeout() {
        return ConfigValues.getSessionTimeout();
    }
    
    @Override
    public void setInfoForSession(String key, String info) {
        super.setInfoForSession(key, info);
    }
    
    @Override
    protected List<String> getSessionPrefixs() {
        return sessionPrefixs;
    }
    
    /**
     * @Title: renewUCUsertoken
     * @Description: 通过用户中心的user_token 和auth_id 获取 user_token
     * @param @param sessionIdentity
     * @param @param user_token
     * @param @return
     * @return String
     * @throws
     */
    public String renewUCUsertoken(SessionIdentity sessionIdentity, String user_token) {
        // 生成会话令牌
        String access_token = user_token;
        // 获得会话令牌key
        String access_tokenKey = getAccess_tokenKey(access_token);
        // 生成字符串信息
        String stringInfo = sessionIdentity.toStringInfo();
        // 根据会话令牌保存信息到缓存
        setInfoForSession(access_tokenKey, stringInfo);
        return access_token;
    }
    
    /**
     * 更换会话令牌，生成一个新的会话令牌并保存会话身份对象
     * 
     * @param sessionIdentity
     *            会话身份对象
     * @return 新生成的会话令牌
     */
    public String renewAccess_token(SessionIdentity sessionIdentity) {
        // 生成会话令牌
        String access_token = IDUtil.genUUID();
        // 获得会话令牌key
        String access_tokenKey = getAccess_tokenKey(access_token);
        // 生成字符串信息
        String stringInfo = sessionIdentity.toStringInfo();
        // 根据会话令牌保存信息到缓存
        setInfoForSession(access_tokenKey, stringInfo);
        return access_token;
    }
    
    /**
     * 根据会话令牌获取保存的会话身份对象
     * 
     * @param access_token
     *            请求携带的会话令牌
     * @return 对应的会话身份对象或者null
     */
    public <T extends SessionIdentity> T fetchSessionIdentityByAccess_token(String access_token, Class<T> clazz) {
        try {
            // 获得会话令牌key
            String access_tokenKey = getAccess_tokenKey(access_token);
            // 从缓存获取会话令牌对应的字符串信息
            String stringInfo = fetchInfoByKey(access_tokenKey);
            // 解析会话身份信息
            if (StringUtils.isNotBlank(stringInfo)) {
                return JSON.parseObject(stringInfo, clazz);
            }
            return null;
        } catch (Exception e) {
            LOGGER.error("fetch SessionIdentity by user_token failed", e);
            return null;
        }
    }
    
    /**
     * 加入到对应大V的在线粉丝list
     * @param brokerId
     */
    public void addListToBrokeyOnline(boolean isNew, String brokerId, String[] fansIds) {
        String brokerOnlineListKey = isNew ? getBrokerOnlineListKey(String.valueOf(brokerId))
                : getOldBrokerOnlineListKey(String.valueOf(brokerId));
        getCacheHelper().sdd(brokerOnlineListKey, fansIds);
    }
    
    /**
     * 加入一个粉丝到对应大V的在线粉丝list
     * @param brokerId
     * @param fansId
     */
    public void addOneToBrokeyOnline(String brokerId, String fansId) {
        String[] fans = { fansId };
        addListToBrokeyOnline(true, brokerId, fans);
    }
    
    /**
     * 移除在线列表中的一个元素
     * @param brokerId
     * @param fansId
     */
    public void removeOnlineFromList(String brokerId, String fansId) {
        getCacheHelper().sremove(getBrokerOnlineListKey(String.valueOf(brokerId)), fansId);
        getCacheHelper().sremove(getOldBrokerOnlineListKey(String.valueOf(brokerId)), fansId);
    }
    
    public Set<String> getNewOnlineList(String brokerId) {
        return getCacheHelper().smembers(getBrokerOnlineListKey(brokerId));
    }
    
    public Set<String> getOldOnlineList(String brokerId) {
        return getCacheHelper().smembers(getOldBrokerOnlineListKey(brokerId));
    }
    
    public void destroyOldOnlineList(String brokerId) {
        getCacheHelper().destroy(getOldBrokerOnlineListKey(brokerId));
    }
    
    public void destroyNewOnlineList(String brokerId) {
        getCacheHelper().destroy(getBrokerOnlineListKey(brokerId));
    }
    
    public void refreshSession(PlatformType type, String access_token, SessionIdentity sessionIdentity) {
        super.refreshSession(access_token);
        String userType = sessionIdentity.getUser_type();
//        if (SysContants.SESSION_USER_TYPE_CLIENT.equals(userType)) {
//            getCacheHelper().refresh(getClient_idKey(type, sessionIdentity.getClient_id().toString()),
//                    getSessionTimeout());
//        } else if (SysContants.SESSION_USER_TYPE_STAFF.equals(userType)) {
//            getCacheHelper()
//                    .refresh(getStaff_idKey(sessionIdentity.getClient_id().toString()), getSessionTimeout());
//        }
    }
    
    public void destroySession(PlatformType type, String access_token, SessionIdentity sessionIdentity) {
        super.destroySession(access_token);
        if (null != sessionIdentity) {
//            getCacheHelper().destroy(getClient_idKey(type, sessionIdentity.getClient_id().toString()));
        }
    }
    
    public String getSessionTokenByClientId(PlatformType type, String client_id) {
        switch (type) {
            case MANAGE:
                return fetchInfoByKey(getBroker_idKey(client_id));
            case MOBILE:
                return fetchInfoByKey(getCustomer_idKey(client_id));
            default:
                return null;
        }
    }
    
    public String getSessionLongTokenByClientId(String client_id) {
        return fetchInfoByKey(getLong_tokenKey(client_id));
    }
    
    public String getSessionDeviceUidByClientId(String client_id) {
        return fetchInfoByKey(getDevice_UidKey(client_id));
    }
    
    public String getWxTicket(Long broker_id) {
        return fetchInfoByKey(CacheKeys.WX_TICKET_PREFIX + broker_id);
    }
    
    public void setWxTicket(Long broker_id, String ticket) {
        this.setInfoForSession(CacheKeys.WX_TICKET_PREFIX + broker_id, ticket);
    }
    
    public Integer getBrokerNoreadQuestionNum(Long brokerId) {
        String numStr = fetchInfoByKey(CacheKeys.BROKER_QUESTION_NOREAD_NUM_PREFIX + brokerId);
        return numStr == null ? 0 : Integer.valueOf(numStr);
    }
    
    public void addBrokerNoreadQuestionNum(Long brokerId) {
        String key = CacheKeys.BROKER_QUESTION_NOREAD_NUM_PREFIX + brokerId;
        String numStr = fetchInfoByKey(key);
        Integer num = numStr == null ? 1 : Integer.valueOf(numStr) + 1;
        this.setInfoForSession(key, String.valueOf(num), -1);
    }
    
    public void clearNoreadQuestionNum(Long brokerId) {
        this.delete(CacheKeys.BROKER_QUESTION_NOREAD_NUM_PREFIX + brokerId);
    }
    
    public String getAccess_tokenKey(String access_token) {
        return CacheKeys.ACCESS_TOKEN_PREFIX + access_token;
    }

    /**
     * 获取管理端token
     * */
    public String getAdmin_token(String user_key){
        return ("admin" + user_key);
    }

    public String getTenantKey(String access_token) {
        return CacheKeys.ACCESS_TOKEN_TENANT_KEY + access_token;
    }
    
    /**
     * 手机号码+verifySource所组成的key - 对应的短信校验码value . 有效期为验证码失效时间
     * */
    public String getMobileVerifyKey(String mobile, String verify_soure) {
        return CacheKeys.MOBILE_VERIFY_PREFIX + mobile + CacheKeys.SEPARATOR + verify_soure;
    }
    
    /**
     * 手机号码+verifySource所组成的key - 存储时记录的时间戳value . 有效期为短信倒计时读秒数
     * */
    public String getSendVerifyKey(String mobile, String verify_source) {
        return CacheKeys.SEND_VERIFY_PREFIX + mobile + CacheKeys.SEPARATOR + verify_source;
    }
    
    /**
     * 手机号码+verifySource所组成的key - 存储时记录的时间戳value . 有效期为配置有效时间
     * */
    public String getSendVerifyKeyConfig(String mobile, String verify_source) {
        return CacheKeys.SEND_VERIFY_HOUR_PREFIX + mobile + CacheKeys.SEPARATOR + verify_source;
    }
    
    /**
     * 手机号码+verifySource所组成的key - 当日发送验证码数量value . 有效期为配置有效时间
     * */
    public String getDailySendVerifySourceKey(String mobile, String verify_source) {
        return CacheKeys.DAILY_SEND_VERIFY_SOURCE + mobile + CacheKeys.SEPARATOR + verify_source;
    }
    
    /**
     * 手机号码+当日年月日yyyyMMdd所组成的key - 当日发送验证码数量value . 有效期为24小时的秒数
     * */
    public String getDailySendVerifyCountKey(String mobile) {
        return CacheKeys.DAILY_SEND_VERIFY_COUNT + mobile + CacheKeys.SEPARATOR
                + DateTimeUtil.getCurrentDateString(DateTimeUtil.FORMAT_YYYYMMDD_NO_BREAK);
    }
    
    public String getCustomer_idKey(String client_id) {
        return CacheKeys.CUSTOMER_ID_PREFIX + client_id;
    }
    
    public String getClient_idKey(PlatformType type, String client_id) {
        switch (type) {
            case MANAGE:
                return getBroker_idKey(client_id);
            case MOBILE:
                return getCustomer_idKey(client_id);
            default:
                return null;
        }
    }
    
    /**
     * 生成的token 保存到clientId 缓存中
     * @param type
     * 
     * @param customer_id
     * @return
     */
    public void saveNewClientIDSession(PlatformType type, Long brokerId, Long customer_id, String access_token,
                                       Integer tenant_id) {
        // 获得client_id会话令牌key getClient_idKey
        String access_tokenKey = SessionHelper.getInstance().getClient_idKey(type, customer_id.toString());
        String stringInfo = SessionHelper.getInstance().getAccess_tokenKey(access_token);
        String tenantKey = SessionHelper.getInstance().getTenantKey(access_token);
        // 根据会话令牌保存信息到缓存
        SessionHelper.getInstance().setInfoForSession(access_tokenKey, stringInfo);
        SessionHelper.getInstance().setInfoForSession(tenantKey, ValueUtil.getString(tenant_id));
        
        //将会话令牌及登录平台信息保存到缓存
        //加入到在线用户列表缓存
        SessionHelper.getInstance().addOneToBrokeyOnline(String.valueOf(brokerId), String.valueOf(customer_id));
    }
    
    public String getBroker_idKey(String client_id) {
        return CacheKeys.BROKER_ID_PREFIX + client_id;
    }
    
    public String getStaff_idKey(String staff_id) {
        return CacheKeys.STAFF_ID_PREFIX + staff_id;
    }
    
    public String getLong_tokenKey(String client_id) {
        return CacheKeys.LONG_TOKEN_PREFIX + client_id;
    }
    
    public String getDevice_UidKey(String client_id) {
        return CacheKeys.DEVICE_UID_PREFIX + client_id;
    }
    
    public String getBrokerOnlineListKey(String broker_id) {
        return CacheKeys.BROKER_ONLINE_LIST + broker_id;
    }
    
    public String getOldBrokerOnlineListKey(String broker_id) {
        return CacheKeys.BROKER_ONLINE_LIST_OLD + broker_id;
    }
    
    public boolean exist(String key) {
        return getCacheHelper().exists(key);
    }

    public String getMarketToken(String key){return getCacheHelper().get(key);}

    public Long getMarketLock(String key){return getCacheHelper().setnx(key);}
    public void delMarketLock(String key){getCacheHelper().delete(key);}
    public String getAskNum(String key){return getCacheHelper().get(key);}
}
